/*
 *
 * Copyright (c) 2006, 2007, 2008 Prabhu Gurumurthy <pgurumur@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef __PY_TRIE_H_
#define __PY_TRIE_H_

#include <sys/types.h>

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include <Python.h>
#include <listobject.h>
#include <structmember.h>

#include "tree.h"

#define TQ_MEMBER(object) struct PyMemberDef object
#define TQ_MEMBER_LIST(a,b,c,d,e) { a, b, c, d, e }
#define TQ_ALLOC(object, type) (object *)type.tp_alloc(&type, 0)
#define TQ_FREE(object) object->ob_type->tp_free((PyObject *)ob)

struct trie {
   RB_ENTRY(trie) entry;
   PyObject *value;
};

typedef struct {
   PyObject_HEAD
   PyObject *converter;
   RB_HEAD(treehead, trie) head;
   int count;
   int closed;
} PyTrieObject;

static PyObject *PyTrie_Error;
extern PyTypeObject PyTrieObjectType;

const char *_PyTrie_Version = "0.1";
static char _PyTrie_Doc[] = "Red black tree in python using OpenBSD tree code";

void inittree(void);

static void _PyTrie_ObjectDeAlloc(PyTrieObject *);
static int _PyTrie_Traverse(PyTrieObject *, visitproc, void *);
static int _PyTrie_SetAttr(PyTrieObject *, char *, PyObject *);
static PyObject *_PyTrie_GetAttr(PyTrieObject *, char *);
static PyObject *PyTrie_Delete(PyTrieObject *, PyObject *);
static void PyTrie_SetError(int, const char *, ...);
static int PyTrie_Compare(struct trie *first, struct trie *second);

static PyObject *PyTrie_Init(PyObject *, PyObject *);
static PyObject *PyTrie_Add(PyTrieObject *, PyObject *);
static PyObject *PyTrie_Remove(PyTrieObject *, PyObject *);
static PyObject *PyTrie_List(PyTrieObject *, PyObject *);
static PyObject *PyTrie_Empty(PyTrieObject *, PyObject *);
static PyObject *PyTrie_Find(PyTrieObject *, PyObject *);
static PyObject *PyTrie_Count(PyTrieObject *, PyObject *);

static PyMethodDef PyTrie_Methods[] = {
   {
      "init",
      (PyCFunction)PyTrie_Init,
      METH_NOARGS,
      NULL
   },
   {
      "add",
      (PyCFunction)PyTrie_Add,
      METH_VARARGS,
      NULL
   },
   {
      "remove",
      (PyCFunction)PyTrie_Remove,
      METH_VARARGS,
      NULL
   },
   {
      "list",
      (PyCFunction)PyTrie_List,
      METH_NOARGS,
      NULL
   },
   {
      "empty",
      (PyCFunction)PyTrie_Empty,
      METH_NOARGS | METH_VARARGS,
      NULL
   },
   {
      "find",
      (PyCFunction)PyTrie_Find,
      METH_VARARGS,
      NULL
   },
   {
      "count",
      (PyCFunction)PyTrie_Count,
      METH_NOARGS,
      NULL,
   },
   { NULL, NULL, 0, NULL },
};

static TQ_MEMBER(_PyTrieObjectMemberList)[] = {
   TQ_MEMBER_LIST(
         "converter", T_OBJECT, offsetof(PyTrieObject, converter), RO,
         "Type conversion mapping"),
   { NULL, 0, 0, 0, NULL }
};


#endif
